<?php

declare(strict_types=1);

namespace app\extend;

use app\service\system\file\FileManage;
use owns\enum\FileEnum;
use owns\facade\HttpClient;
use think\facade\Cache;
use think\facade\Config;

/**
 * 微信小程序
 */
class WeChatApplet
{
    private $wx;

    public function __construct()
    {
        $this->getConfig();
    }
    /**
     * 微信配置
     */
    private function getConfig(): void
    {
        $this->wx = Config::get('pay.wechat.default');
    }
    /**
     * 获取AccessToken
     */
    public function getAccessToken(): string
    {
        //获取缓存 access_token
        $accessToken = Cache::get('wx_access_token');
        if (!$accessToken) {
            $param = [
                'grant_type' => 'client_credential',
                'appid' => $this->wx['mini_app_id'],
                'secret' => $this->wx['mini_secret'],
            ];
            $response = HttpClient::post('https://api.weixin.qq.com/cgi-bin/token', $param);
            if (isset($response['errcode']) && $response['errcode'] != 0) {
                tips('获取微信签名失败');
            }
            //放入缓存
            $accessToken = $response['access_token'];
            Cache::set('wx_access_token', $accessToken, 6000);
        }
        return $accessToken;
    }
    /**
     * 获取微信授权手机号
     * @param $code
     */
    public function getUserPhone($code): array
    {
        $url = 'https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token=' . $this->getAccessToken();
        $response = HttpClient::post($url, ['code' => $code], [
            "Content-type:text/plain;charset='utf-8'",
            "Accept:application/json"
        ]);
        if (isset($response['errcode']) && $response['errcode'] != 0) {
            tips('获取手机号失败');
        }
        return $response;
    }
    /**
     * 获取微信用户openid
     * @param string $code
     */
    public function getWxOpenId(string $code): string
    {
        $param = [
            'appid' => $this->wx['mini_app_id'],
            'secret' => $this->wx['mini_secret'],
            'js_code' => $code,
            'grant_type' => 'authorization_code',
        ];
        $response = HttpClient::get('https://api.weixin.qq.com/sns/jscode2session', $param);
        if (isset($response['errcode']) && $response['errcode'] != 0) {
            tips('请重新授权登录');
        }
        $openid = $response['openid'] ?? '';
        if (!$openid) {
            tips('请重新授权登录');
        }
        return $openid;
    }
    /**
     * 生成微信小程序邀请二维码(不限制)
     * @param string $page 例如：'pages/index/index'
     * @param string $param
     */
    public function getWxQrcode(string $page, string $param): string
    {
        $response = HttpClient::get(
            'https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=' . $this->getAccessToken(),
            ['page' => $page, 'scene' => $param, 'width' => 200, 'is_hyaline' => true, 'env_version' => 'release']
        );
        if (isset($response['errcode'])) {
            tips('获取邀请二维码失败，' . $response['errmsg']);
        }
        //将数据流写入文件
        return make(FileManage::class)->localSave($response, '.png', FileEnum::QRCODE);
    }
    /**
     * 扫普通链接二维码打开小程序
     * @param string $code 扫码获取参数
     */
    public function linkQrCode(string $code)
    {
        $url = 'https://www.project-domain.com';
        //二维码配置
        $config = [
            'logo' => 1,
            'foreground' => '#ffffff',
            'background' => '#096ac7',
            'size' => '300',
            'padding' => '10',
            'logosize' => 80,
            'errorcorrection' => 'high',
            'text' => $url . '?code=' . $code,
        ];
        //校验文件路径
        $verifyFile = '/qrcode/build?';

        return $url . $verifyFile . http_build_query($config);
    }
    /**
     * 消息订阅发送
     * @param string $template_id 模板id
     * @param string $openid 订阅用户
     * @param array $data 模板信息
     */
    public function messageSend($template_id, $openid, $data): void
    {
        $response = HttpClient::post(
            'https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=' . $this->getAccessToken(),
            [
                'template_id' => $template_id,
                'touser' => $openid,
                'data' => $data,
                'miniprogram_state' => 'formal',
                'lang' => 'zh_CN',
            ]
        );
        if (isset($response['errcode']) && $response['errcode']) {
            tips('消息发送失败：' . $response['errmsg'] ?? '');
        }
    }
}
